<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script id="TextureVS" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    attribute vec4 a_Color;
    uniform float u_PointSize;
    uniform mat4 u_ModelM4;
    varying vec4 v_Color;
    void main(){
        gl_Position = u_ModelM4 * a_Position;
        gl_PointSize = 30.0;
        v_Color = a_Color;
    }
</script>
<script id="TextureFS" type="x-shader/x-fragment">
    precision mediump float;
    varying vec4 v_Color;
    void main(){
        gl_FragColor = v_Color;
    }
</script>
<script id="ColorVS" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    attribute vec2 a_Pin;
    uniform mat4 u_ModelM4;
    uniform mat4 u_PvM4;
    varying vec2 v_Pin;
    void main(){
        gl_Position = u_PvM4 * u_ModelM4 * a_Position;
        gl_PointSize = 30.0;
        v_Pin = a_Pin;
    }
</script>
<script id="ColorFS" type="x-shader/x-fragment">
    precision mediump float;
    uniform sampler2D u_Sampler;
    varying vec2 v_Pin;
    void main(){
        gl_FragColor = texture2D(u_Sampler, v_Pin);
        //gl_FragColor = vec4(1.0,1.0,1.0,1.0);
    }
</script>
<script type="module">
    import { Matrix4, Vector3, Color, OrthographicCamera, PerspectiveCamera, Spherical } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Poly from '../js/Poly4.js'
    import Control from '../js/Control.js'

    import Geo from '../js/Poly2/Geo.js'
    import Mat from '../js/Poly2/Mat.js'
    import Obj3D from '../js/Poly2/Obj3D.js'
    import Scene from '../js/Poly2/Scene.js'



    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight - 4;

    const gl = canvas.getContext("webgl", { antialias: true, });

    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    gl.enable(gl.DEPTH_TEST);
    //#endregion

    const textureProgram = CreateProgram(gl,
        document.querySelector('#TextureVS').innerText,
        document.querySelector('#TextureFS').innerText);
    const colorProgram = CreateProgram(gl,
        document.querySelector('#ColorVS').innerText,
        document.querySelector('#ColorFS').innerText);


    const pvM4 = new Matrix4();
    const modelM4 = new Matrix4();

    const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 1, 20);
    const cameraController = new CameraController({
        canvas,
        camera,
        pvMatrix: pvM4
    });



    //#region 绘制贴图
    let textureBuffer = null;
    const texturePoint = [256, 256];
    //绘制图像
    {
        const verticesArr = [
            -1, 1, 0, 1, 1, 1,
            -1, -1, 0, 0, 1, 1,
            1, -1, 1, 0, 1, 1,
            1, 1, 1, 1, 1, 1,
        ];
        const elementsArr = [
            0, 1, 2, 0, 2, 3,
        ];

        gl.useProgram(textureProgram);
        const a_Position = gl.getAttribLocation(textureProgram, 'a_Position');
        const a_Color = gl.getAttribLocation(textureProgram, 'a_Color');
        const u_PointSize = gl.getUniformLocation(textureProgram, 'u_PointSize');
        const u_ModelM4 = gl.getUniformLocation(textureProgram, 'u_ModelM4');

        const verticesBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, verticesBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArr), gl.STATIC_DRAW);
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 6 * 4, 0 * 4);
        gl.enableVertexAttribArray(a_Position);
        gl.vertexAttribPointer(a_Color, 4, gl.FLOAT, false, 6 * 4, 2 * 4);
        gl.enableVertexAttribArray(a_Color);
        // const colorsBuffer = gl.createBuffer();
        // gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
        // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorArr), gl.STATIC_DRAW);
        // gl.vertexAttribPointer(a_Color, 4, gl.FLOAT, false, 0, 0);
        // gl.enableVertexAttribArray(a_Color);
        const elementsBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementsBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(elementsArr), gl.STATIC_DRAW);

        gl.uniform1f(u_PointSize, 20);
        gl.uniformMatrix4fv(u_ModelM4, false, new Matrix4().elements);
    }
    //创建纹理对象
    {
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
        gl.activeTexture(gl.TEXTURE0);
        textureBuffer = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, textureBuffer);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);//设置滤波器
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texturePoint[0], texturePoint[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    }
    //创建帧缓冲区
    {
        const frameBuffer = gl.createFramebuffer();
        gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureBuffer, 0);
    }
    //渲染贴图
    {
        //获取画布尺寸
        // console.log(gl.getParameter(gl.VIEWPORT));
        //设置渲染尺寸, 只绘制指定大小的贴图
        gl.viewport(0, 0, texturePoint[0], texturePoint[1]);
        gl.clearColor(0, 0, 0, 1);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);

        //置空帧缓冲区(一定要置空, 不然下一次绘制还会绘制在帧缓冲区中)
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
        //恢复画布的渲染尺寸
        gl.viewport(0, 0, canvas.width, canvas.height);

    }

    //#endregion

    //#region 创建物体
    let vertices = [];
    //创建物体对象
    {
        //复杂的版本
        const len = 0.3;
        const verticesArr = [
            -len, len, -len,
            -len, len, len,
            len, len, len,
            len, len, -len,
            -len, -len, -len,
            -len, -len, len,
            len, -len, len,
            len, -len, -len,
        ];
        const elementsArr = [
            0, 1, 2, 0, 2, 3,
            1, 5, 6, 1, 6, 2,
            5, 4, 7, 5, 7, 6,
            4, 0, 3, 4, 3, 7,
            2, 6, 7, 2, 7, 3,
            0, 4, 5, 0, 5, 1,
        ];

        vertices = getTrangle(verticesArr, elementsArr);
        const pins = getPin1(elementsArr);


        gl.useProgram(colorProgram);
        const a_Position = gl.getAttribLocation(colorProgram, 'a_Position');
        const a_Pin = gl.getAttribLocation(colorProgram, 'a_Pin');
        const u_ModelM4 = gl.getUniformLocation(colorProgram, 'u_ModelM4');
        const u_PvM4 = gl.getUniformLocation(colorProgram, 'u_PvM4');
        const u_Sampler = gl.getUniformLocation(colorProgram, 'u_Sampler');

        const positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
        gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Position);
        const pinBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, pinBuffer)
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pins), gl.STATIC_DRAW);
        gl.vertexAttribPointer(a_Pin, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Pin);

        gl.uniformMatrix4fv(u_ModelM4, false, new Matrix4().elements);
        gl.uniformMatrix4fv(u_PvM4, false, pvM4.elements);

        gl.bindTexture(gl.TEXTURE_2D, textureBuffer)
        gl.uniform1i(u_Sampler, 0);


        // gl.clearColor(0, 0, 0, 1);
        // gl.clear(gl.COLOR_BUFFER_BIT);
        // gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
    }
    {
        //简单的版本
        const len = 0.3;
        const verticesArr = [
            -len, len, -len,
            -len, len, len,
            len, len, len,
            len, len, -len,
            -len, -len, -len,
            -len, -len, len,
            len, -len, len,
            len, -len, -len,
        ];
        const elementsArr = [
            0, 1, 2, 0, 2, 3,
            1, 5, 6, 1, 6, 2,
            5, 4, 7, 5, 7, 6,
            4, 0, 3, 4, 3, 7,
            2, 6, 7, 2, 7, 3,
            0, 4, 5, 0, 5, 1,
        ];
        const pinArr = [
            1, 1, 0, 1, 1, 1, 0, 1,
            1, 0, 0, 0, 1, 0, 0, 0,
        ];


        gl.useProgram(colorProgram);
        const a_Position = gl.getAttribLocation(colorProgram, 'a_Position');
        const a_Pin = gl.getAttribLocation(colorProgram, 'a_Pin');
        const u_ModelM4 = gl.getUniformLocation(colorProgram, 'u_ModelM4');
        const u_PvM4 = gl.getUniformLocation(colorProgram, 'u_PvM4');
        const u_Sampler = gl.getUniformLocation(colorProgram, 'u_Sampler');

        const positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArr), gl.STATIC_DRAW);
        gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Position);
        const pinBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, pinBuffer)
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pinArr), gl.STATIC_DRAW);
        gl.vertexAttribPointer(a_Pin, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Pin);
        const elementBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(elementsArr), gl.STATIC_DRAW);

        gl.uniformMatrix4fv(u_ModelM4, false, new Matrix4().elements);
        gl.uniformMatrix4fv(u_PvM4, false, pvM4.elements);

        gl.bindTexture(gl.TEXTURE_2D, textureBuffer)
        gl.uniform1i(u_Sampler, 0);


        // gl.clearColor(0, 0, 0, 1);
        // gl.clear(gl.COLOR_BUFFER_BIT);
        // gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
    }
    //#endregion






    function getTrangle(vertices, elements) {
        const arr = [];
        const node = (index) => {
            return new Vector3(vertices[index * 3], vertices[index * 3 + 1], vertices[index * 3 + 2]);
        };
        for (let i = 0; i < elements.length; i += 3) {
            arr.push(...node(elements[i]));
            arr.push(...node(elements[i + 1]));
            arr.push(...node(elements[i + 2]));
        }
        return arr;
    }

    function getPin1(elements) {
        const arr = [];
        for (let i = 0; i < elements.length; i++) {
            //貌似解决不了上下角
            switch (elements[i]) {
                case 1:
                    arr.push(0, 1);
                    break;
                case 2:
                    arr.push(1, 1);
                    break;
                case 5:
                    arr.push(0, 0);
                    break;
                case 6:
                    arr.push(1, 0);
                    break;

                case 0:
                    arr.push(1, 1);
                    break;
                case 3:
                    arr.push(0, 1);
                    break;
                case 4:
                    arr.push(1, 0);
                    break;
                case 7:
                    arr.push(0, 0);
                    break;
            }

        }
        return arr;
    }

    gl.useProgram(colorProgram);
    let u_PvM4 = gl.getUniformLocation(colorProgram, 'u_PvM4');
    (function ani() {

        gl.uniformMatrix4fv(u_PvM4, false, pvM4.elements);

        gl.clear(gl.COLOR_BUFFER_BIT);
        // gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3);
        gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);

        requestAnimationFrame(ani);
    })();

    function draw() {
        gl.clearColor(0, 0, 0, 1);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.drawElements(gl.TRIANGLES, elementsArr.length, gl.UNSIGNED_SHORT, 0);
    }
</script>

</html>